#include "SQLWithSubqueryClause.h"

#include "../SQLObject.h"
#include "../../visitor/SQLASTVisitor.h"
#include "../../../utils/ifeq.h"

SQLWithSubqueryClause::SQLWithSubqueryClause()
{
  entries = std::make_shared<std::list<std::shared_ptr<SQLWithSubqueryClause_Entry>>>();
}

SQLObject_ptr SQLWithSubqueryClause::clone()
{
  SQLObject_ptr clone_tmp = SQLWithSubqueryClause_ptr(new SQLWithSubqueryClause());
  SQLWithSubqueryClause_ptr x = std::dynamic_pointer_cast<SQLWithSubqueryClause>(clone_tmp);
  // SQLWithSubqueryClause *x = new SQLWithSubqueryClause();
  x->recursive = recursive;

  for (std::shared_ptr<SQLWithSubqueryClause_Entry> entry : *entries)
  {
    std::shared_ptr<SQLWithSubqueryClause_Entry> entry2 = std::dynamic_pointer_cast<SQLWithSubqueryClause_Entry>(entry->clone());
    entry2->setParent(x);
    x->entries->push_back(entry2);
  }

  return x;
}

std::shared_ptr<std::list<std::shared_ptr<SQLWithSubqueryClause_Entry>>> SQLWithSubqueryClause::getEntries()
{
  return entries;
}

void SQLWithSubqueryClause::addEntry(std::shared_ptr<SQLWithSubqueryClause_Entry> entry)
{
  if (entry != NULL)
  {
    entry->setParent(SharedObject(SQLWithSubqueryClause));
  }
  this->entries->push_back(entry);
}

BOOL_ptr SQLWithSubqueryClause::getRecursive()
{
  return recursive;
}

void SQLWithSubqueryClause::setRecursive(BOOL_ptr recursive)
{
  this->recursive = recursive;
}

void SQLWithSubqueryClause::accept0(SQLASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(SQLWithSubqueryClause)))
  {
    auto it_entries = entries->begin();
    for (int i = 0; i < entries->size(); i++)
    {
      // Entry* entry = entries->get(i);
      std::advance(it_entries, i);
      std::shared_ptr<SQLWithSubqueryClause_Entry> entry = *it_entries;
      if (entry != NULL)
      {
        entry->accept(visitor);
      }
    }
  }
  visitor->endVisit(SharedObject(SQLWithSubqueryClause));
}

std::shared_ptr<SQLWithSubqueryClause_Entry> SQLWithSubqueryClause::findEntry(long alias_hash)
{
  if (alias_hash == 0)
  {
    return NULL;
  }

  for (std::shared_ptr<SQLWithSubqueryClause_Entry> entry : *entries)
  {
    if (entry->aliasHashCode64() == alias_hash)
    {
      return entry;
    }
  }

  return NULL;
}

bool SQLWithSubqueryClause::equals(Object_ptr o)
{
  if (this == o.get())
  {
    return true;
  }
  if (o == NULL || getClass() != o->getClass())
  {
    return false;
  }

  SQLWithSubqueryClause_ptr that = std::dynamic_pointer_cast<SQLWithSubqueryClause>(o);

  if (recursive != BOOL::NIL ? !(recursive == that->recursive) : that->recursive != BOOL::NIL)
  {
    return false;
  }
  return IFEQ::ifeq<SQLWithSubqueryClause_Entry_ptr>(entries,that->entries);
  // return BOOL::FALSE;
}

int SQLWithSubqueryClause::hashCode()
{
  int result = recursive == BOOL::FALSE ? 1 : 0;
  // result = 31 * result + entries->hashCode();
  return result;
}
